package com.ys.service.storage.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.entity.purchase.TcgPurchaseAppointOrder;
import com.ys.entity.purchase.TcgPurchaseAppointOrderItem;
import com.ys.entity.purchase.TcgPurchaseAppointOrderProductComponent;
import com.ys.entity.purchase.TcgPurchaseContractItem;
import com.ys.entity.purchase.TcgPurchaseInStorage;
import com.ys.entity.purchase.TcgPurchasePreStorageSon;
import com.ys.entity.storage.TccAssemble;
import com.ys.entity.storage.TccAssembleError;
import com.ys.entity.storage.TccAssembleItem;
import com.ys.entity.storage.TccStockControl;
import com.ys.enume.storage.TccAssembleEnum;
import com.ys.enume.storage.TccStockSourceEnum;
import com.ys.mapper.storage.StorageMapper;
import com.ys.mapper.storage.TccAssembleItemMapper;
import com.ys.mapper.storage.TccAssembleMapper;
import com.ys.service.storage.TccAssembleErrorService;
import com.ys.service.storage.TccAssembleService;
import com.ys.service.storage.TccPutonService;
import com.ys.service.storage.TccStockControlService;
import com.ys.vo.R;

@Service("tccAssembleService")
public class TccAssembleImpl implements TccAssembleService {

	@Autowired
	private StorageMapper storageMapper;
	@Autowired
	private TccAssembleMapper tccAssembleMapper;
	@Autowired
	private TccAssembleItemMapper tccAssembleItemMapper;
	@Autowired
	private TccPutonService tccPutonService;
	@Autowired
	private TccAssembleErrorService tccAssembleErrorService;
	@Autowired
	private TccStockControlService tccStockControlService;

	@Override
	public R add(String bid) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@Transactional
	public R pass(String bid) throws Exception {
		TccAssemble tccAssemble = new TccAssemble().setBid(bid).queryFirst();
		if (tccAssemble == null) {
			return R.error("数据不存在");
		} else if (tccAssemble.getState() != TccAssembleEnum.State.NOT.value) {
			return R.error("数据已组装");
		}
		
		tccAssemble
			.setParentAssembleNumber(tccAssemble.getParentPreAssembleNumber())
			.setState(TccAssembleEnum.State.YES.value)
			.setAuditTime(new Date());
		tccAssembleMapper.update(tccAssemble);
		
		// 子件出库
		List<TccAssembleItem> listTccAssembleItem = new TccAssembleItem().setPbid(bid).queryList();
		for(TccAssembleItem item : listTccAssembleItem) {
			// 子件的剩余数量更新为0
			item.setSubAssembleLeftNum(0)
				.setSubRealStorageNum(item.getSubRealStorageNum());
			tccAssembleItemMapper.update(item);
			
			Long id = item.getStockControlId();
			String remark = "商品组装单单号：" + bid + "，正常组装，子件出库";
			Integer numOut = item.getSubRealStorageNum();
			Integer source = TccStockSourceEnum.Source.TCC_Assemble.value;
			Long sourceId = item.getId();
			tccStockControlService.outWithRunning(id, remark, numOut, bid,source,sourceId);
		}
		

		TcgPurchaseAppointOrderItem tcgPurchaseAppointOrderItem = new TcgPurchaseAppointOrderItem().setId(tccAssemble.getAppointOrderItemId()).queryFirst();
		TcgPurchaseAppointOrder tcgPurchaseAppointOrder = new TcgPurchaseAppointOrder().setBid(tcgPurchaseAppointOrderItem.getPbid()).queryFirst();
		
		// 母件入库
		R add;
		{
			String rkBid = bid;
			String chw = "HW00001";
			String productName = tcgPurchaseAppointOrderItem.getProductName();
			Integer productNum = 0;
			String productCode = tcgPurchaseAppointOrderItem.getProductCode();
			Integer productNumAll = tccAssemble.getParentAssembleNumber();
			BigDecimal purchasePrice = storageMapper.countPurchaseByPurchaseAppointOrderItem(tccAssemble.getAppointOrderItemId());
			BigDecimal purchaseTotalPriceAll = purchasePrice.multiply(new BigDecimal(productNum));
			BigDecimal allotPrice = purchasePrice;
			BigDecimal totalAllotPrice = purchaseTotalPriceAll;
			String vgsbm = tcgPurchaseAppointOrder.getVgsbm();
			Date drksj = new Date();
			Integer isParent = 1;
			String sourceBid = bid;
			Integer source = TccStockSourceEnum.Source.TCC_Assemble.value;
			String remark = "";
			String companyVid = tcgPurchaseAppointOrder.getCompanyVid();
			Long sourceId = tccAssemble.getId();
			add = tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, source, remark, companyVid,bid,sourceId);
		}

		// 生成质检上架单
		tccPutonService.add(bid, 1, tccAssemble.getParentAssembleNumber(),Long.valueOf(add.get("data").toString()));
		
		return R.ok("操作成功");
	}
	
	@Override
	@Transactional
	public R doError(String bid, Integer parentAssembleNumber, String detailArr) throws Exception {
		
		TccAssemble tccAssemble = new TccAssemble().setBid(bid).queryFirst();
		// 验证组装单
		if (tccAssemble == null) {
			return R.error("数据不存在");
		} else if (tccAssemble.getState() != TccAssembleEnum.State.NOT.value) {
			return R.error("非待组装状态");
		} else if (tccAssemble.getParentPreAssembleNumber() < parentAssembleNumber) {
			return R.error("组装数量超过预计组装数量");
		}
		
		// 验证详情数据不能为空
		JSONArray detailJA = JSON.parseArray(detailArr);
		if (detailJA == null || detailJA.size() == 0) {
			return R.error("详情数据不能为空");
		}
		
		/*
		 *  验证详情数据剩余数量不能小于0
		 *  组装单子表数据与详情数据的ID一致
		 *  实际入库数量不能高于计划入库数量，实际入库数量= 母件组装数量*子件BOM数量+子件组装剩余数量
		 */
		List<TccAssembleItem> listTccAssembleItem = new TccAssembleItem().setPbid(bid).queryList();
		if (listTccAssembleItem.size() != detailJA.size()) {
			return R.error("子列表数据大小有误");
		}
		Map<Long, TccAssembleItem> ID_ENTITY_MAP = new HashMap<Long, TccAssembleItem>();
		for(TccAssembleItem item : listTccAssembleItem) {
			ID_ENTITY_MAP.put(item.getId(), item);
		}
		for (int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");
			if (subLeftNumber == null || subLeftNumber < 0) {
				return R.error("子件剩余数量不能为负");
			}
			
			Long id = detailJO.getLong("id");
			if (!ID_ENTITY_MAP.containsKey(id)) {
				return R.error("数据有误");
			}
			
			// 实际入库数量不能高于子件计划入库数量
			Integer subRealStorageNum = parentAssembleNumber * detailJO.getInteger("subBomNumber") + subLeftNumber;
			TccAssembleItem item = ID_ENTITY_MAP.get(id);
			if (subRealStorageNum > item.getSubPlanStorageNum()) {
				return R.error("剩余数量与组装数量总和不能高于计划入库数量");
			}
		}
		
		tccAssemble
			.setParentAssembleNumber(parentAssembleNumber)
			.setState(TccAssembleEnum.State.YES.value)
			.setAuditTime(new Date());
		tccAssembleMapper.update(tccAssemble);

//		// 子件编码-异常单号MAP
//		Map<String, String> SubCode_ErrorBid_MAP = new HashMap<String, String>();
		// 子件出库
		for(int i = 0; i < detailJA.size(); i++) {
			JSONObject detailJO = detailJA.getJSONObject(i);
			Long id = detailJO.getLong("id");
			TccAssembleItem item = ID_ENTITY_MAP.get(id);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");

			// 子件组装实际入库数量 = 母件组装数量 * 子件BOM数量 + 子件剩余数量
			Integer subRealStorageNum = parentAssembleNumber * detailJO.getInteger("subBomNumber") + subLeftNumber;
			
			// 更新组装单子表的子件剩余数量和子件实际入库数量
			storageMapper.updateTccAssembleItemOfNum(id, subLeftNumber, subRealStorageNum);

			Long stockControlId = item.getStockControlId();
			String remark = "商品组装单单号：" + bid + "，异常组装，子件缺失出库";
			// 出库数量 = 实际组装消耗的数量
			Integer numOut = item.getSubRealStorageNum();
			Integer sourceType = TccStockSourceEnum.Source.TCC_Assemble.value;
			Long sourceId = id;
			tccStockControlService.outWithRunning(stockControlId, remark, numOut, bid,sourceType,sourceId);


			// 子件组装实际入库数量 = 母件组装数量 * 子件BOM数量 + 子件剩余数量
			// 子件缺失数量 = 子件计划入库数量-子件实际入库数量
			Integer subAssembleLostNum = item.getSubPlanStorageNum() - subRealStorageNum;
			
			// 生成组装报错单，缺失数量大于0才生成
			Long assembleItemId = id;
			if (subAssembleLostNum > 0) {
				TccAssembleError tccAssembleError = tccAssembleErrorService.add(assembleItemId, subAssembleLostNum);
//				SubCode_ErrorBid_MAP.put(detailJO.getString("subCode"), tccAssembleError.getBid());
			}
		}

		TcgPurchaseAppointOrderItem tcgPurchaseAppointOrderItem = new TcgPurchaseAppointOrderItem().setId(tccAssemble.getAppointOrderItemId()).queryFirst();
		TcgPurchaseAppointOrder tcgPurchaseAppointOrder = new TcgPurchaseAppointOrder().setBid(tcgPurchaseAppointOrderItem.getPbid()).queryFirst();
		
		
		// 剩余子件入库
		for(int i = 0; i < detailJA.size(); i++) {
			
			JSONObject detailJO = detailJA.getJSONObject(i);
			Long id = detailJO.getLong("id");
			TccAssembleItem item = ID_ENTITY_MAP.get(id);
			Integer subLeftNumber = detailJO.getInteger("subLeftNumber");
			
			if (subLeftNumber > 0) {
				
				Long appointOrderComponentId = item.getAppointOrderComponentId();
				TcgPurchaseAppointOrderProductComponent tcgPurchaseAppointOrderProductComponent = new TcgPurchaseAppointOrderProductComponent().setId(appointOrderComponentId).queryFirst();
				
				TcgPurchaseInStorage tcgPurchaseInStorage = new TcgPurchaseInStorage().setId(item.getPurchaseStorageId()).queryFirst();
				TcgPurchasePreStorageSon tcgPurchasePreStorageSon = new TcgPurchasePreStorageSon().setId(tcgPurchaseInStorage.getPurchasePreStorageSonId()).queryFirst();
				TcgPurchaseContractItem tcgPurchaseContractItem = new TcgPurchaseContractItem().setId(tcgPurchasePreStorageSon.getPurchaseContractItemId()).queryFirst();
				
				Long stockControlId = item.getStockControlId();
				TccStockControl tccStockControl = new TccStockControl().setId(stockControlId).queryFirst();
				String rkBid = null;
				String chw = tccStockControl.getChw();
				String productName = tcgPurchaseAppointOrderProductComponent.getSubName();
				Integer productNum = subLeftNumber;
				String productCode = tcgPurchaseAppointOrderProductComponent.getSubCode();
				Integer productNumAll = subLeftNumber;
				BigDecimal purchasePrice = tcgPurchaseContractItem.getSubPurchasePrice();
				BigDecimal purchaseTotalPriceAll = tcgPurchaseContractItem.getPurchaseTotalPrice();
				BigDecimal allotPrice = null;
				BigDecimal totalAllotPrice = null;
				String vgsbm = tcgPurchaseAppointOrder.getVgsbm();
				Date drksj = new Date();
				Integer isParent = 0;
				String sourceBid = bid;
//				String sourceBid = SubCode_ErrorBid_MAP.get(tcgPurchaseAppointOrderProductComponent.getSubCode());
				Integer sourceType = TccStockSourceEnum.Source.TCC_Assemble.value;
				String remark = "商品组装单单号：" + bid + "，异常组装，剩余子件入库";
				String companyVid = tcgPurchaseAppointOrder.getCompanyVid();
				String assembleBid = bid;
				//来源id
				Long sourceId = item.getId();
				tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, sourceType, remark, companyVid, assembleBid,sourceId);
			}
		}
		
		// 母件入库
		R add;
		{
			String rkBid = bid;
			String chw = "HW00001";
			String productName = tcgPurchaseAppointOrderItem.getProductName();
			Integer productNum = 0;
			String productCode = tcgPurchaseAppointOrderItem.getProductCode();
			Integer productNumAll = tccAssemble.getParentAssembleNumber();
			BigDecimal purchasePrice = storageMapper.countPurchaseByPurchaseAppointOrderItem(tccAssemble.getAppointOrderItemId());
			BigDecimal purchaseTotalPriceAll = purchasePrice.multiply(new BigDecimal(productNum));
			BigDecimal allotPrice = purchasePrice;
			BigDecimal totalAllotPrice = purchaseTotalPriceAll;
			String vgsbm = tcgPurchaseAppointOrder.getVgsbm();
			Date drksj = new Date();
			Integer isParent = 1;
			String sourceBid = bid;
			Integer sourceType = TccStockSourceEnum.Source.TCC_Assemble.value;
			String remark = "";
			String companyVid = tcgPurchaseAppointOrder.getCompanyVid();
			Long sourceId = tccAssemble.getId();
			add = tccStockControlService.inWithRunning(rkBid, chw, productName, productNum, productCode, productNumAll, purchasePrice, purchaseTotalPriceAll, allotPrice, totalAllotPrice, vgsbm, drksj, isParent, sourceBid, sourceType, remark, companyVid,bid,sourceId);
		}

		// 生成质检上架单
		tccPutonService.add(bid, 1, parentAssembleNumber,Long.valueOf(add.get("data").toString()));
		
		return R.ok();
	}
}
